game.tsx ➔ getData   A
last analyzed

Complexity

Conditions 1

Size

Total Lines 3
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 3
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 1
1
import ReactFitText from "@kennethormandy/react-fittext"
2
import { useState, useEffect, Fragment } from "react"
3
import { useSiteMetaData } from "../hooks/use-site-metadata"
4
import iconBench from "../images/i_bench_2.png"
5
import iconCardRed from "../images/i_card_red.png"
6
import iconCardYellow from "../images/i_card_yellow.png"
7
import iconCardYellowRed from "../images/i_card_yellow_red.png"
8
import iconGoal from "../images/i_goal.png"
9
import iconStart from "../images/i_start.png"
10
import iconSubIn from "../images/i_sub_in.png"
11
import iconSubOut from "../images/i_sub_out.png"
12
import { MatchDetails, MatchDetailsEventItem, MatchDetailsLineupItem, MatchDetailsSubstituteItem } from "../Types/Match"
13
import { GamePageProps } from "../Types/PageProps"
14
import { DateTime, Settings } from "luxon"
15
import React from "react"
16
import Layout from "../layouts"
17
import { Spinner } from "../components/Spinner"
18
import { Seo } from "../components/Seo"
19
import "./game.scss"
20
import { mapPsdStatus, request } from "../scripts/helper"
21
import LazyLoad from "react-lazy-load"
22
import Icon from "../components/Icon"
23
import { MiniRanking } from "../components/MiniRanking"
24
const GamePage = ({ matchId }: GamePageProps) => {
25
  const { kcvvPsdApi } = useSiteMetaData()
26
  const [data, setData] = useState<MatchDetails>()
27
28
  useEffect(() => {
29
    async function getData() {
30
      const response = await request.get(`${kcvvPsdApi}/match/${matchId}`)
31
      setData(response.data)
32
    }
33
    getData()
34
  }, [kcvvPsdApi, matchId])
35
36
  Settings.defaultZone = `Europe/Brussels`
37
  Settings.defaultLocale = `nl-be`
38
39
  if (matchId === null) {
40
    return (
41
      <Layout>
42
        <main className="page__wrapper">Geen match beschikbaar...</main>
43
      </Layout>
44
    )
45
  }
46
47
  if (data) {
48
    const { general, substitutes, lineup, events = [] } = data || {}
49
    const { home: homeLineup = [], away: awayLineup = [] } = lineup || {}
50
    const { home: homeSubs = [], away: awaySubs = [] } = substitutes || {}
51
52
    const matchTime = DateTime.fromFormat(general.date, `yyyy-MM-dd HH:mm`)
53
    const homeTeamId = general.homeClub?.id
54
55
    const ogImage = {
56
      src: general?.homeClub?.logo,
57
      width: 180,
58
      height: 180,
59
    }
60
61
    return (
62
      <Layout>
63
        <Seo
64
          title={`Matchverslag ${general.homeClub?.abbreviation || general?.homeClub?.name} - ${
65
            general.awayClub?.abbreviation || general?.awayClub?.name
66
          }`}
67
          description={`Matchverslag ${general.homeClub?.abbreviation || general?.homeClub?.name} - ${
68
            general.awayClub?.abbreviation || general?.awayClub?.name
69
          }`}
70
          path={`/game/${general?.id}`}
71
          image={ogImage}
72
        />
73
        <header className="game__header__wrapper full-width">
74
          <div className="game__header__inner">
75
            <div className="game__teams">
76
              <div className={`game__teams-inner`}>
77
                <LazyLoad>
78
                  <img src={general.homeClub?.logo} alt={general.homeClub?.name} title={general.homeClub?.name} />
79
                </LazyLoad>
80
              </div>
81
              {renderScore(general.goalsHomeTeam, general.goalsAwayTeam)}
82
              <div className={`game__teams-inner`}>
83
                <LazyLoad>
84
                  <img src={general.awayClub?.logo} alt={general.awayClub?.name} title={general.awayClub?.name} />
85
                </LazyLoad>
86
              </div>
87
            </div>
88
            <h1>
89
              <ReactFitText compressor={2.5}>{`${general.homeClub?.abbreviation || general.homeClub?.name} - ${
90
                general.awayClub?.abbreviation || general.awayClub?.name
91
              }`}</ReactFitText>
92
            </h1>
93
            <h4>{general.competitionType}</h4>
94
            <time dateTime={matchTime.toFormat(`EEEE dd LLLL - H:mm`)}>
95
              {matchTime.toFormat(`EEEE dd LLLL - H:mm`)}
96
            </time>
97
            <br />
98
99
            {general.status !== 0 && (
100
              <span className={`game__status game__status--${general.status}`}>{mapPsdStatus(general.status)}</span>
101
            )}
102
103
            <br />
104
          </div>
105
        </header>
106
107
        <main className="page__wrapper">
108
          {(homeLineup.length !== 0 || awayLineup.length !== 0) && (
109
            <div className={`lineup__wrapper`}>
110
              <div className={`lineup__wrapper--home`}>
111
                <h3>{general.homeClub?.abbreviation || general.homeClub?.name}</h3>
112
                {homeLineup && renderLineup(homeLineup, homeSubs)}
113
              </div>
114
              <div className={`lineup__wrapper--away`}>
115
                <h3>{general.awayClub?.abbreviation || general.awayClub?.name}</h3>
116
                {awayLineup && renderLineup(awayLineup, awaySubs)}
117
              </div>
118
            </div>
119
          )}
120
        </main>
121
122
        <section className="page__wrapper">
123
          {events.length !== 0 && (
124
            <div className={`event__wrapper`}>
125
              <h3>Gebeurtenissen</h3>
126
              {events && renderEvents(events, homeTeamId)}
127
            </div>
128
          )}
129
130
          {general.competitionType === `Competitie` && (
131
            <MiniRanking
132
              teamId={general.homeTeamId || general.awayTeamId || 0}
133
              homeTeam={general.homeClub?.name}
134
              awayTeam={general.awayClub?.name}
135
            />
136
          )}
137
        </section>
138
      </Layout>
139
    )
140
  } else {
141
    return (
142
      <Layout>
143
        <Spinner />
144
      </Layout>
145
    )
146
  }
147
}
148
149
const renderScore = (resultHome?: number, resultAway?: number) => {
150
  return resultHome !== null && resultAway !== null ? (
151
    <div className={`game__details__vs game__details__vs--score`}>
152
      {renderScoreWithWinnerIndicator(resultHome || 0, resultAway || 0, `home`)}
153
      <span className={`match-details__divider`}>&nbsp;-&nbsp;</span>
154
      {renderScoreWithWinnerIndicator(resultAway || 0, resultHome || 0, `away`)}
155
    </div>
156
  ) : (
157
    <div className={`game__details__vs`}>VS</div>
158
  )
159
}
160
161
const renderScoreWithWinnerIndicator = (result1: number, result2: number, extraClass?: string) => {
162
  return result1 > result2 ? (
163
    <span className={`game__details__winner game__details__winner--${extraClass}`}>{result1}</span>
164
  ) : (
165
    <span className={`game__details__loser`}>{result1}</span>
166
  )
167
}
168
169
const renderLineup = (lineup: MatchDetailsLineupItem[], substitutes: MatchDetailsSubstituteItem[]) => {
170
  return (
171
    <Fragment>
172
      {renderLineupHeader()}
173
      {lineup.map((element, i) => renderLineupLine(i, element))}
174
      <hr />
175
      {substitutes.map((element, i) => renderSubLine(i, element))}
176
    </Fragment>
177
  )
178
}
179
180
const renderLineupHeader = () => {
181
  return (
182
    <div className={`lineup__header`}>
183
      <span className={`lineup__header__item lineup__item--status`}></span>
184
      <span className={`lineup__header__item lineup__item--number`}>#</span>
185
      <span className={`lineup__header__item lineup__item--name`}>Name</span>
186
      <span className={`lineup__header__item lineup__item--time`}>
187
        <Icon icon="fa-clock-o" />
188
      </span>
189
    </div>
190
  )
191
}
192
193
const renderLineupLine = (i: React.Key, element: MatchDetailsLineupItem) => {
194
  return (
195
    <div className={`lineup__row lineup__row--lineup`} key={i}>
196
      <span
197
        className={`lineup__row__item lineup__item--status`}
198
        style={{
199
          backgroundImage: `url(${element.changed ? iconSubOut : iconStart})`,
200
        }}
201
        title={`${element.changed ? `Basisspeler gewisseld` : `Basisspeler`}`}
202
      ></span>
203
      <span className={`lineup__row__item lineup__item--number`}>{element.number}</span>
204
      <span className={`lineup__row__item lineup__item--name`}>
205
        {element.playerName} {element.captain && `(C)`}
206
      </span>
207
      <span className={`lineup__row__item lineup__item--time`}>{element.minutesPlayed}'</span>
208
    </div>
209
  )
210
}
211
212
const renderSubLine = (i: React.Key, element: MatchDetailsSubstituteItem) => {
213
  return (
214
    <div className={`lineup__row lineup__row--substitute`} key={i}>
215
      <span
216
        className={`lineup__row__item lineup__item--status`}
217
        style={{
218
          backgroundImage: `url(${element.changed ? iconSubIn : iconBench})`,
219
        }}
220
        title={`${element.changed ? `Wisselspeler ingevallen` : `Wisselspeler`}`}
221
      ></span>
222
      <span className={`lineup__row__item lineup__item--number`}>{element.number}</span>
223
      <span className={`lineup__row__item lineup__item--name`}>{element.playerName}</span>
224
      <span className={`lineup__row__item lineup__item--time`}>{element.minutesPlayed}'</span>
225
    </div>
226
  )
227
}
228
229
const renderEvents = (events: MatchDetailsEventItem[], homeTeamId: number) => {
230
  return <Fragment>{events.map((element, i) => renderEventLine(i, element, homeTeamId))}</Fragment>
231
}
232
233
const renderEventLine = (i: React.Key, element: MatchDetailsEventItem, homeTeamId: number) => {
234
  const homeTeam = element.clubId == homeTeamId
235
  let actionIcon = null
236
  let actionMessage = ``
237
  let actionText = ``
238
239
  // Backwards compatibility:
240
  if (typeof element.action === `string`) {
241
    switch (element.action) {
242
      case `geel`:
243
        actionIcon = iconCardYellow
244
        actionText = `Gele kaart voor`
245
        actionMessage = `Gele kaart`
246
        break
247
      case `rood`:
248
        actionIcon = iconCardRed
249
        actionText = `Rode kaart voor`
250
        actionMessage = `Rode kaart`
251
        break
252
      case `tweedegeel`:
253
        actionIcon = iconCardYellowRed
254
        actionText = `Tweede gele kaart voor`
255
        actionMessage = `Tweede gele kaart`
256
        break
257
      case `doelpunt`:
258
        actionIcon = iconGoal
259
        actionText = `${element?.goalsHome} - ${element?.goalsAway} — Doelpunt gescoord door`
260
        actionMessage = `Doelpunt`
261
        break
262
      case `minuteOut`:
263
        actionIcon = iconSubOut
264
        actionText = `Speler uit:`
265
        actionMessage = `Wissel`
266
        break
267
      case `minuteIn`:
268
        actionIcon = iconSubIn
269
        actionText = `Speler in:`
270
        actionMessage = `Wissel`
271
        break
272
    }
273
  } else {
274
    switch (element.action.type) {
275
      case `GOAL`:
276
        actionIcon = iconGoal
277
        actionText = `${element?.goalsHome} - ${element?.goalsAway} — Doelpunt gescoord door`
278
        actionMessage = `Doelpunt`
279
        break
280
      case `CARD`:
281
        switch (element.action.subtype) {
282
          case `YELLOW`:
283
            actionIcon = iconCardYellow
284
            actionText = `Gele kaart voor`
285
            actionMessage = `Gele kaart`
286
            break
287
          case `RED`:
288
            actionIcon = iconCardRed
289
            actionText = `Rode kaart voor`
290
            actionMessage = `Rode kaart`
291
            break
292
          case `DOUBLE_YELLOW`:
293
            actionIcon = iconCardYellowRed
294
            actionText = `Tweede gele kaart voor`
295
            actionMessage = `Tweede gele kaart`
296
            break
297
        }
298
    }
299
  }
300
301
  return (
302
    <div className={`event__row ${homeTeam ? `event__row--home` : `event__row--away`}`} key={i}>
303
      {homeTeam && (
304
        <span className={`event__row__item event__row__item--home lineup__item--name`}>
305
          {actionText} {element.playerName}
306
        </span>
307
      )}
308
      {homeTeam && (
309
        <span
310
          className={`event__row__item event__row__item--home lineup__item--action center`}
311
          style={{ backgroundImage: `url(${actionIcon})` }}
312
          title={actionMessage}
313
        ></span>
314
      )}
315
      <span className={`event__row__item lineup__item--time center`}>{element.minute}'</span>
316
      {homeTeam || (
317
        <span
318
          className={`event__row__item event__row__item--away lineup__item--action center`}
319
          style={{ backgroundImage: `url(${actionIcon})` }}
320
          title={actionMessage}
321
        ></span>
322
      )}
323
      {homeTeam || (
324
        <span className={`event__row__item event__row__item--away lineup__item--name`}>
325
          {actionText} {element.playerName}
326
        </span>
327
      )}
328
    </div>
329
  )
330
}
331
332
export default GamePage
333